#import <Foundation/Foundation.h>
#import <objc/runtime.h>

#import "framework/FWCommon.h"

#import "PIAlarm.h"


@implementation PIAlarm

@synthesize key, date, relativeDate, type, location, coordinates;


// ******************************************************************************************
#pragma mark -
#pragma mark Global sort functions

NSInteger compareAlarmTimes(id obj1, id obj2, void *context)
{
    return [((PIAlarm*)obj1).date compare:((PIAlarm*)obj2).date];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Initialisation and object management

+ (PIAlarm*)alarmWithKey:(NSString*)newKey date:(NSDate*)newDate type:(kPIEventAlarmType)newType;
{
    PIAlarm* alarm = [[[PIAlarm alloc] init] autorelease];
    
    alarm->key = [newKey copy];
    alarm->date = [newDate retain];
    alarm->type = newType;
    alarm->relativeDate = 0;
    
    return alarm;
}

+ (PIAlarm*)alarmWithKey:(NSString*)newKey relativeDate:(NSTimeInterval)newRelative baseDate:(NSDate*)newDate type:(kPIEventAlarmType)newType
{
    PIAlarm* alarm = [[[PIAlarm alloc] init] autorelease];
    
    alarm->key = [newKey copy];
    alarm->date = [[newDate addTimeInterval:newRelative] retain];
    alarm->type = newType;
    alarm->relativeDate = newRelative;
    
    return alarm;
}

+ (PIAlarm*)alarmWithKey:(NSString*)newKey type:(kPIEventAlarmType)newType location:(NSString*)newLocation coordinates:(NSString*)newCoordinates
{
    PIAlarm* alarm = [[[PIAlarm alloc] init] autorelease];
    
    alarm->key = [newKey copy];
    alarm->type = newType;
    alarm->location = [newLocation copy];
    alarm->coordinates = [newCoordinates copy];
    
    return alarm;
}

- (void)dealloc
{
    [key release];
    [date release];
    
    [location release];
    [coordinates release];
    
    [super dealloc];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Access functions

- (BOOL)isRelative
{
    return relativeDate != 0;
}


- (void)expireAlarm
{
    [date release];
    date = [[NSDate date] retain];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Debugging functions

- (NSString*)description
{
    NSString* typeName;
    switch (type) {
        case kPIEventAlarmTypeExtraReminder:
            typeName = @"EXTRA-REMINDER";
            break;
        case kPIEventAlarmTypeExtraAlarm:
            typeName = @"EXTRA-ALARM";
            break;
        case kPIEventAlarmTypeNative:
            typeName = @"NATIVE";
            break;
        case kPIEventAlarmTypeAlarmIsActive:
            typeName = @"IS-ACTIVE";
            break;
        case kPIEventAlarmTypeLocationLeave:
            typeName = @"LOCN-LEAVE";
            break;
        case kPIEventAlarmTypeLocationArrive:
            typeName = @"LOCN-ARRIVE";
            break;
        default:
            typeName = [NSString stringWithFormat:@"%i", type];
            break;
    }
    
    return [NSString stringWithFormat:
            @"<%@: %p;"
            " key = %@;"
            " date = %@;"
            " type = %@;"
            " locn = %@;"
            " coord = %@>",
            [self class],
            self,
            key,
            date,
            typeName,
            location,
            coordinates];
}

@end


// ******************************************************************************************
#pragma mark -
#pragma mark Object access from arrays

@implementation NSArray (PIAlarm)

- (id)piAlarmForKey:(NSString*)key
{
    NSInteger count = self.count;
    for (NSInteger i = 0; i < count; ++i) {
        PIAlarm* obj = [self objectAtIndex:i];
        if ([obj.key isEqualToString:key])
            return obj;
    }
    
    return nil;
}

- (id)piAlarmForKey:(NSString*)key type:(kPIEventAlarmType)type
{
    NSInteger count = self.count;
    for (NSInteger i = 0; i < count; ++i) {
        PIAlarm* obj = [self objectAtIndex:i];
        if ((obj.type == type) && [obj.key isEqualToString:key])
            return obj;
    }
    
    return nil;
}

@end
